package wsresource.server;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import wstm.client.WSTransactionManager;
import wstm.client.WSTransactionManagerService;

public class ResourceManager {
  //Singleton
  private static ResourceManager instance = new ResourceManager();
  public static ResourceManager getInstance() {
    return instance;
  }

  protected Map<String, Context> contextByXID = new HashMap<String, Context>();
  protected WSTransactionManagerService tmService;
  protected WSTransactionManager transactionManager;

  public ResourceManager() {
    tmService = new WSTransactionManagerService();
    transactionManager = tmService.getWSTransactionManagerPort();
  }
  public Context getContextByXID(String xid) {
    Context ret = contextByXID.get(xid);
    if (ret == null) {
      throw new IllegalStateException(xid);
    }
    return ret;
  }

  public Context createContextByXID(String xid) {
    if (contextByXID.containsKey(xid)) {
      throw new IllegalStateException(xid);
    }
    Context ret = new Context();
    contextByXID.put(xid, ret);
    return ret;
  }

  public boolean existContextByXID(String xid) {
    return contextByXID.containsKey(xid);
  }

  public boolean enrol(String xid, String RMurl) throws Exception {
    return transactionManager.enrol(xid, RMurl);
  }
  
  public void markForRollback(String xid){
    getContextByXID(xid).toRollback = true;
  }
  
  public Connection getConnection(String xid, WSResource wsRes) throws Exception{
    if(existContextByXID(xid)){
      return getContextByXID(xid).conn;
    }    
    //Enrol de resource
    if (ResourceManager.getInstance().enrol(xid,wsRes.getProperties().getProperty("RMurl"))){
      //In enrol the context is created
      //Obtain the connection object from the WSResource
      Connection conn = wsRes.beginConnection();
      Context ctx = getContextByXID(xid);
      ctx.conn=conn;
      ctx.localAutoCommitMode = conn.getAutoCommit();
      conn.setAutoCommit(false);
      //Begin the local transacction 
      try {
        System.out.println("Execute statment BEGIN;");
        conn.createStatement().executeUpdate("BEGIN;");
      } catch (SQLException e) {
        System.err.println("Cannot Execute statment 'BEGIN;'");
        System.err.println(e.getMessage());
        ctx.toRollback = true;
       return null;
      }
      return conn;
    }
    else{
      System.err.println("Cannot enrol in the transaction");
      Context ctx = getContextByXID(xid);
      ctx.toRollback = true;
      return null;
    }   
  }
  
  public void endConnection(String xid, WSResource wsRes) throws Exception{
    wsRes.endConnection(getContextByXID(xid).conn);
  }
}
